﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CjcAwesomiumWrapper;
using System.Windows.Media;
using System.Windows;
using System.IO;
using System.ComponentModel;

namespace Cjc.ChromiumBrowser
{
	public struct EnvironmentSettings
	{
		public string UserDataPath { get; set; }
		public string PlugInPath { get; set; }
		public string LogPath { get; set; }
		public string UserAgentOverride { get; set; }

		public EnvironmentSettings( string userDataPath = "", string plugInPath = "", string logPath = "", string userAgentOverride = "" )
			: this()
		{
			this.UserDataPath = userDataPath;
			this.PlugInPath = plugInPath;
			this.LogPath = logPath;
			this.UserAgentOverride = userAgentOverride;
		}

		public static EnvironmentSettings Default
		{
			get
			{
				return new EnvironmentSettings(
					"", "", "", "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/531.3 (KHTML, like Gecko) Chrome/4.0.249.89 Safari/531.3" );
					// "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.89 Safari/532.5"
			}
		}
	}

	public class WebBrowserEnvironment
	{
		private static WebCore webCore;
		private static EnvironmentSettings settings = EnvironmentSettings.Default;
		private static HashSet<WeakReference<WebView>> webViews = new HashSet<WeakReference<WebView>>();

		public static WebView CreateWebView( int width, int height )
		{
			Purge();

			lock ( webViews )
			{
				if ( webCore == null ) CreateWebCore();

				var webView = webCore.CreateWebView( width, height );

				webViews.Add( new WeakReference<WebView>( webView ) );

				return webView;
			}
		}

		public static EnvironmentSettings Settings
		{
			get { return settings; }
			set
			{
				Purge();

				lock ( webViews )
				{
					if ( webCore != null ) throw new InvalidOperationException( "Cannot change settings while WebViews are active" );
					settings = value;
				}
			}
		}

		public static void Purge( bool force = false )
		{
			lock ( webViews )
			{
				if ( force ) webViews.Clear();
				else webViews.RemoveWhere( v => !v.IsAlive );

				if ( webCore != null && webViews.Count < 1 ) ReleaseWebCore();
			}
		}

		private static void CreateWebCore()
		{
			var config = new WebCoreConfig();

			webCore = new WebCore( config );

			CompositionTarget.Rendering += OnUpdate;
			Application.Current.MainWindow.Closing += OnExit;
		}

		private static void ReleaseWebCore()
		{
			if ( webCore != null )
			{
				try
				{
					CompositionTarget.Rendering -= OnUpdate;
					Application.Current.MainWindow.Closing -= OnExit;
				}
				catch { }

				webCore.Dispose();
				webCore = null;

				GC.Collect();
			}
		}

		private static void OnExit( object sender, CancelEventArgs e )
		{
            if (Application.Current.Windows.Count > 1) { Purge(false); } else { Purge(true); }
		}

		private static void OnUpdate( object sender, EventArgs e )
		{
			if ( webCore != null ) webCore.Update();
		}
	}
}
